﻿/*
    Copyright (C) 2008, wj2929, wj2929@gmail.com

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    *KEEP THIS HEADER INFORMATION*
*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using mjRegister.Entity;
using System.Xml.Linq;
using System.Xml;
using System.IO;
using System.Net;
using System.Threading;

namespace mjRegister.BAL
{
    //账户
    public class Account
    {
        private static Mutex mutex = new Mutex(false);   

        public static string GetAccountActiveStatusDesctiption(ActiveStatus activeStatus)
        { 
            string activeStatusDesctiption = string.Empty ;
            switch (activeStatus)
            {
                case ActiveStatus.NoVerifyActive:
                    activeStatusDesctiption = "未验证";
                    break;
                case ActiveStatus.NoActive:
                    activeStatusDesctiption = "未激活(或账户密码错误或被封)";
                    break;
                case ActiveStatus.AlreadyActive:
                    activeStatusDesctiption = "已激活账户";
                    break;
                case ActiveStatus.AppForbided:
                    activeStatusDesctiption = "组件被封";
                    break;
            }
            return activeStatusDesctiption;
        }

        public static void EditAccountInfo(IList<AccountInfo> accountInfos)
        {
            mutex.WaitOne();

            XDocument xmlAccount = XDocument.Load(GetAccountXmlFile());

            for (int i = 0; i < accountInfos.Count; i++)
            {
                AccountInfo accountInfo = accountInfos[i];
                var xeAccounts = xmlAccount.Root.Elements("Account").Where(g => g.Element("Email").Value == accountInfo.Email);

                if (xeAccounts.Count() > 0)
                {
                    XElement xeAccount = xeAccounts.ToList()[0];

                    xeAccount.Element("Password").Value = accountInfo.Password;

                    if (accountInfo.AccountGroupInfo != null)
                        xeAccount.Element("AccoutGroupId").Value = accountInfo.AccountGroupInfo.Id.ToString();

                    xeAccount.Element("ActiveStatus").Value = ((int)accountInfo.ActiveStatus).ToString();

                    if (xeAccount.Element("IsMaster") == null)
                        xeAccount.Add(new XElement("IsMaster", accountInfo.IsMaster.ToString()));
                    else
                        xeAccount.Element("IsMaster").Value = accountInfo.IsMaster.ToString();

                    if (accountInfo.UserInfo != null)
                    {
                        if (xeAccount.Element("UserInfo") == null)
                        {
                            xeAccount.Add(new XElement("UserInfo",
                                new XElement("uid", accountInfo.UserInfo.uid),
                                new XElement("real_name", accountInfo.UserInfo.real_name),
                                new XElement("nick", accountInfo.UserInfo.nick),
                                new XElement("gender", accountInfo.UserInfo.gender),
                                new XElement("logo120", accountInfo.UserInfo.logo120),
                                new XElement("logo50", accountInfo.UserInfo.logo50),
                                new XElement("logo25", accountInfo.UserInfo.logo25),
                                new XElement("hometown", accountInfo.UserInfo.hometown),
                                new XElement("city", accountInfo.UserInfo.city),
                                new XElement("isfriend", accountInfo.UserInfo.isfriend.ToString()),
                                new XElement("commentright", accountInfo.UserInfo.commentright.ToString()),
                                new XElement("authentication", Common.SerializeObject(accountInfo.UserInfo.AuthenticationCookieCollection))
                               )
                            );
                        }
                        else
                        {
                            var xeUserInfo = xeAccount.Element("UserInfo");
                            xeUserInfo.Element("uid").Value = accountInfo.UserInfo.uid;
                            xeUserInfo.Element("real_name").Value = accountInfo.UserInfo.real_name;
                            xeUserInfo.Element("nick").Value = accountInfo.UserInfo.nick;
                            xeUserInfo.Element("gender").Value = accountInfo.UserInfo.gender;
                            xeUserInfo.Element("logo120").Value = accountInfo.UserInfo.logo120;
                            xeUserInfo.Element("logo50").Value = accountInfo.UserInfo.logo50;
                            xeUserInfo.Element("logo25").Value = accountInfo.UserInfo.logo25;
                            xeUserInfo.Element("hometown").Value = accountInfo.UserInfo.hometown;
                            xeUserInfo.Element("city").Value = accountInfo.UserInfo.city;
                            xeUserInfo.Element("isfriend").Value = accountInfo.UserInfo.isfriend.ToString();
                            xeUserInfo.Element("commentright").Value = accountInfo.UserInfo.commentright.ToString();
                            if (accountInfo.UserInfo.AuthenticationCookieCollection != null)
                            {
                                if (xeUserInfo.Element("authentication") == null)
                                    xeUserInfo.Add(new XElement("authentication", Common.SerializeObject(accountInfo.UserInfo.AuthenticationCookieCollection)));
                                else
                                    xeUserInfo.Element("authentication").Value = Common.SerializeObject(accountInfo.UserInfo.AuthenticationCookieCollection);
                            }
                        }
                    }
                }
            }

            xmlAccount.Save(GetAccountXmlFile());

            mutex.ReleaseMutex();
        }

        public static void EditAccountInfo(AccountInfo accountInfo)
        {
            IList<AccountInfo> accountInfos = new List<AccountInfo>();
            accountInfos.Add(accountInfo);
            EditAccountInfo(accountInfos);
        }

        public static void StaticFriends(AccountInfo accountInfo)
        {
            mutex.WaitOne();
            string friendxmlfile = Path.Combine(Common.GetConfigPath(), string.Format("{0}_friends.xml", accountInfo.UserInfo.uid));
            string friendxmltempfile = Path.Combine(Common.GetConfigPath(), string.Format("{0}_friends_temp.xml", accountInfo.UserInfo.uid));

            if (File.Exists(friendxmltempfile))
                File.Delete(friendxmltempfile);

            XElement xmlFriends = new XElement("Friends");
            for (int j = 0; j < accountInfo.FriendInfos.Count; j++)
            {
                SimpleUserInfo simpleUserInfo = accountInfo.FriendInfos[j];
                if (simpleUserInfo.uid != accountInfo.UserInfo.uid)
                {
                    xmlFriends.Add(new XElement("Friend",
                        new XElement("uid", simpleUserInfo.uid),
                        new XElement("real_name", simpleUserInfo.real_name),
                        new XElement("real_name_unsafe", simpleUserInfo.real_name_unsafe)
                        )
                    );
                }
            }
            using (XmlTextWriter writer = new XmlTextWriter(friendxmltempfile, Encoding.UTF8))
                xmlFriends.WriteTo(writer);

            if (File.Exists(friendxmlfile))
                File.Delete(friendxmlfile);

            File.Move(friendxmltempfile, friendxmlfile);

            mutex.ReleaseMutex();
        }

        public static void CreateAccountXmlFile()
        {
            XElement xmlAccounts = new XElement("Accounts");
            using (XmlTextWriter writer = new XmlTextWriter(GetAccountXmlFile(), Encoding.UTF8))
                xmlAccounts.WriteTo(writer);
        }

        static string GetAccountXmlFile()
        {
            return Path.Combine(Common.GetConfigPath(), "accounts.xml");
        }

        public static bool CheckAccountXmlFileExist()
        {
            return File.Exists(GetAccountXmlFile());
        }

        public static void Add(AccountInfo accountInfo)
        {
            mutex.WaitOne();

            XDocument xmlAccount = XDocument.Load(GetAccountXmlFile());

            xmlAccount.Root.Add(new XElement("Account",
                new XElement("Email", accountInfo.Email),
                new XElement("Password", accountInfo.Password),
                new XElement("ActiveStatus", ((int)ActiveStatus.NoVerifyActive).ToString()),
                new XElement("AccoutGroupId",accountInfo.AccountGroupInfo == null ? string.Empty : accountInfo.AccountGroupInfo.Id.ToString())
                )
            );

            xmlAccount.Save(GetAccountXmlFile());

            mutex.ReleaseMutex();
        }

        public static void DeleteByAccountGroup(AccountGroupInfo accountGroupInfo)
        {
            mutex.WaitOne();

            XDocument xmlAccount = XDocument.Load(GetAccountXmlFile());

            var xeAccounts = xmlAccount.Root.Elements("Account").Where(g => g.Element("AccoutGroupId").Value == accountGroupInfo.Id.ToString());

            foreach (XElement xeAccount in xeAccounts)
            {
                if (xeAccount.Element("UserInfo") != null)
                {
                    string frienduid = xeAccount.Element("UserInfo").Element("uid").Value;
                    //删除好友缓存
                    string friendsxml = Path.Combine(Common.GetConfigPath(), string.Format("{0}_friends.xml", frienduid));
                    if (File.Exists(friendsxml))
                        File.Delete(friendsxml);
                }
            }
            xeAccounts.Remove();
            xmlAccount.Save(GetAccountXmlFile());

            mutex.ReleaseMutex();
        }

        public static void Delete(IList<AccountInfo> accountInfos)
        {
            mutex.WaitOne();

            XDocument xmlAccount = XDocument.Load(GetAccountXmlFile());

            string[] emails = GetArray<string>.Get(accountInfos.Select(a => a.Email).ToList());

            var xeAccounts = xmlAccount.Root.Elements("Account").Where(g => emails.Contains(g.Element("Email").Value));

            xeAccounts.Remove();

            for (int i = 0; i < accountInfos.Count; i++)
            {
                AccountInfo accountInfo = accountInfos[i];
                //删除好友缓存
                if (accountInfo.UserInfo != null)
                {
                    string friendsxml = Path.Combine(Common.GetConfigPath(), string.Format("{0}_friends.xml", accountInfo.UserInfo.uid));
                    if (File.Exists(friendsxml))
                        File.Delete(friendsxml);
                }
            }

            xmlAccount.Save(GetAccountXmlFile());

            mutex.ReleaseMutex();
        }

        public static void Delete(AccountInfo accountInfo)
        {
            IList<AccountInfo> accountInfos = new List<AccountInfo>();
            accountInfos.Add(accountInfo);
            Delete(accountInfos);
        }

        public static IList<AccountInfo> GetAccountInfos()
        {
            IList<AccountInfo> accountInfos = new List<AccountInfo>();

            XDocument xmlAccount = XDocument.Load(GetAccountXmlFile());

            var xeAccounts = xmlAccount.Root.Elements("Account");

            foreach (XElement xeAccount in xeAccounts)
            {
                AccountInfo accountInfo = new AccountInfo
                {
                    Email = xeAccount.Element("Email").Value,
                    Password = xeAccount.Element("Password").Value,
                    AccountGroupInfo = xeAccount.Element("AccoutGroupId") == null ? null : string.IsNullOrEmpty(xeAccount.Element("AccoutGroupId").Value) ? null : AccountGroup.GetAccountGroupInfoById(new Guid(xeAccount.Element("AccoutGroupId").Value)),
                    ActiveStatus = (ActiveStatus)int.Parse(xeAccount.Element("ActiveStatus").Value),
                    IsMaster = xeAccount.Element("IsMaster") == null ? false : bool.Parse(xeAccount.Element("IsMaster").Value)
                };
                if (xeAccount.Element("UserInfo") != null)
                {
                    XElement xeUserInfo = xeAccount.Element("UserInfo");
                    accountInfo.UserInfo = new UserInfo
                    {
                        uid = xeUserInfo.Element("uid").Value,
                        real_name = xeUserInfo.Element("real_name").Value,
                        nick = xeUserInfo.Element("nick").Value,
                        gender = xeUserInfo.Element("gender").Value,
                        logo120 = xeUserInfo.Element("logo120").Value,
                        logo50 = xeUserInfo.Element("logo50").Value,
                        logo25 = xeUserInfo.Element("logo25").Value,
                        hometown = xeUserInfo.Element("hometown").Value,
                        city = xeUserInfo.Element("city").Value,
                        isfriend = int.Parse(xeUserInfo.Element("isfriend").Value),
                        commentright = int.Parse(xeUserInfo.Element("commentright").Value)
                    };
                    if (xeUserInfo.Element("authentication") != null)
                    {
                        try
                        {
                            accountInfo.UserInfo.AuthenticationCookieCollection = (CookieCollection)Common.DeserializeObject(xeUserInfo.Element("authentication").Value);
                        }
                        catch { }
                    }
                    string accountfriendxmlfile = Path.Combine(Common.GetConfigPath(), string.Format("{0}_friends.xml", accountInfo.UserInfo.uid));
                    if (File.Exists(accountfriendxmlfile))
                    {
                        accountInfo.FriendInfos = new List<SimpleUserInfo>();
                        XDocument xmlAccount_Friends = XDocument.Load(accountfriendxmlfile);
                        var xeAccount_Friends = xmlAccount_Friends.Root.Elements("Friend");
                        foreach (XElement xeAccount_Friend in xeAccount_Friends)
                        {
                            accountInfo.FriendInfos.Add(new SimpleUserInfo
                            {
                                uid = xeAccount_Friend.Element("uid").Value,
                                real_name = xeAccount_Friend.Element("real_name").Value,
                                real_name_unsafe = xeAccount_Friend.Element("real_name_unsafe").Value
                            });
                        }
                    }
                }
                accountInfos.Add(accountInfo);
            }
            return accountInfos;
        }
    }
}
